package cn.learn.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.micrometer.core.instrument.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Map;

/**
 * json工具类
 *
 * @author huangyezhan
 * @version 1.0
 * @date 2020年05月30日15:53
 */
public class JsonUtil {
    private static final Logger logger = LoggerFactory.getLogger(JsonUtil.class);

    private JsonUtil() {
    }

    private static final ObjectMapper MAPPER = new ObjectMapper();

    /**
     * 对象转成json格式的字符串
     *
     * @param obj 对象
     * @return 返回json格式的string
     */
    public static String obj2String(Object obj) {
        if (obj == null) {
            return null;
        }
        try {
            return obj instanceof String ? (String) obj : MAPPER.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            logger.warn("jackson对象转字符串异常", e);
            return null;
        }
    }

    /**
     * 对象转Json格式字符串(格式化的Json字符串)
     *
     * @param obj 对象
     * @return 美化的Json格式字符串
     */
    public static <T> String obj2StringPretty(T obj) {
        if (obj == null) {
            return null;
        }
        try {
            return obj instanceof String ? (String) obj : MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            logger.warn("jackson对象转字符串异常：{}", e.getMessage());
            return null;
        }
    }

    /**
     * String 转 object对象
     *
     * @param str 字符串
     * @param clz 指定数据类型
     * @param <T> 指定的泛型
     * @return 返回转换后的对象
     */
    public static <T> T string2Obj(String str, Class<T> clz) {
        if (StringUtils.isBlank(str) || clz == null) {
            return null;
        }
        try {
            return MAPPER.readValue(str, clz);
        } catch (JsonProcessingException e) {
            logger.info("jackson的string转对象异常", e);
            return null;
        }
    }

    /**
     * 把json字符串转成map
     *
     * @param str json字符串
     * @return 返回map对象
     */
    public static Map string2Map(String str) {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        try {
            return MAPPER.readValue(str, Map.class);
        } catch (JsonProcessingException e) {
            logger.info("jackson的string转对象异常", e);
            return null;
        }
    }

    /**
     * 集合对象与Json字符串之间的转换
     *
     * @param str           要转换的字符串
     * @param typeReference 集合类型如List<Object>
     * @param <T>           指定泛型
     * @return 返回转换后的集合
     */
    public static <T> T string2Collection(String str, TypeReference<T> typeReference) {
        if (StringUtils.isBlank(str) || typeReference == null) {
            return null;
        }
        try {
            return (T) (typeReference.getType().equals(String.class) ? str : MAPPER.readValue(str, typeReference));
        } catch (IOException e) {
            logger.warn("jackson的string转对象异常", e);
            return null;
        }
    }


    /**
     * 集合对象与Json字符串之间的转换
     *
     * @param str           要转换的字符串
     * @param collectionClz 集合类型
     * @param elementClzs   自定义对象的class对象
     * @param <T>           指定的泛型
     * @return 返回转换后的集合
     */
    public static <T> T string2Collection(String str, Class<?> collectionClz, Class<?>... elementClzs) {
        JavaType javaType = MAPPER.getTypeFactory().constructParametricType(collectionClz, elementClzs);
        try {
            return MAPPER.readValue(str, javaType);
        } catch (IOException e) {
            logger.warn("jackson的string转对象异常：{}" + e.getMessage());
            return null;
        }
    }


}
